home *** CD-ROM | disk | FTP | other *** search
Text File | 1988-06-17 | 15.4 KB | 756 lines | [TEXT/EDIT] |
- \ ObjectFORTH.9 by
-
- \ Wayne Joerding
- \ S.E. 430 Dilke St.
- \ Pullman, WA 99163
-
- \ Copywrite 1988 by Wayne Joerding for MacTutor
-
- only mac
- also forth
-
-
- $4EBA CONSTANT JSR_d(PC)
- $4E75 CONSTANT RTS
-
- $203C Constant MOVE.L_#,D0
- $41FB08FA Constant LEA_$-6(PC,D0.L),A0
- $2D08 Constant MOVE.L_A0,-(A6)
-
- : Defer.Not.Init ." Uninitialized" abort ;
- : Defer
- Create -4 ALLOT JSR_d(PC) W,
- ['] Defer.Not.Init HERE - W, RTS W,
- ;
- : Let: ( -- cfa+2 ) ' 2 + ;
- : Do: ( cfa -- ) ' over - swap W! ;
-
- \ ==== ObjectFORTH =======================
-
- 20 4 * CONSTANT Maxnest
- VARIABLE Ostack
-
- \ ---- Allocate space for Object Stack ---
- Ostack 4 + maxnest + Ostack ! maxnest Vallot
-
- GLOBAL
- : Init.Ostack Ostack 4 + maxnest + Ostack ! ;
-
- \ ============================================
- CREATE ObjectFORTH
-
- \ ------ Section defining words --------------
- GLOBAL Defer :Class
- GLOBAL Defer :Instance
- GLOBAL Defer ;Class
- GLOBAL Defer ;Instance
- GLOBAL Defer Hide
-
- CREATE Ob.DefWords
- \ ============================================
- GLOBAL
- CODE DictBase@ ( -- n )
- MOVE.L $-532(A5),-(A6) RTS
- END-CODE MACH
-
- : Relink.DefWords
- [ ' Ob.DefWords body>link dup @ swap
- DictBase@ - swap ] literal literal DictBase@ + !
- ;
- : Delink.DefWords
- [ ' Ob.DefWords body>link ' ObjectFORTH
- body>link over swap - swap DictBase@ - swap ]
- literal literal DictBase@ + !
- ;
-
-
- \ ==== Global Variables for Class Definition ===
- VARIABLE #class.Size
- VARIABLE #ins.Size
- VARIABLE #Forth.Head
- VARIABLE #c.Head
- VARIABLE #c.Pub.Tail
- VARIABLE #c.Pvt.Tail
- VARIABLE #i.Head
- VARIABLE #i.Pub.Tail
- VARIABLE #i.Pvt.Tail
- VARIABLE #parent
- VARIABLE #C.or.I?
-
- \ ====== Object stack ===========================
- GLOBAL
- : Opush ( n -- ) \ push from Pstack to Ostack
- Ostack dup @ 4 - =
- IF ." Ostack overflow" abort THEN
- Ostack -4 over +! @ !
- ;
-
- GLOBAL
- : Opop ( -- ) \ discard top number on Ostack.
- Ostack dup maxnest + 4 + swap @ =
- IF ." Ostack underflow" abort THEN
- 4 Ostack +!
- ;
-
- GLOBAL
- : Ocop+ ( n -- n+os ) \ add Ostack to Pstack.
- Ostack @ @ +
- ;
-
- GLOBAL
- : Ocop ( -- os ) \ copy Ostack to Pstack.
- Ostack @ @
- ;
-
-
- \ ==== Data Structure Defining Words =============
- GLOBAL VARIABLE Offset
-
- GLOBAL
- : Ins.Array ( size -- ) ( name -IN- )
- \ Make a new instance variable of 'size' bytes.
- CREATE immediate
- Offset @ , \ store offset
- dup 2 mod + \ make sure even number
- Offset +! \ increase offset
- DOES> ( ob.DFA -OS- ob.DFA )
- @ [compile] literal
- compile Ocop+
- ;
-
- GLOBAL
- : I.Var ( -- ) ( name -IN- )
- 4 Ins.Array
- ;
-
- GLOBAL
- : I.Pntr ( -- ) ( name -IN- )
- \ Make ivar without incrementing.
- CREATE immediate
- offset @ , \ compile offset.
- DOES> ( ob.DFA -OS- ob.DFA )
- @ [compile] literal
- compile Ocop+
- ;
-
- \ ==== Method defining word =======================
- GLOBAL
- : :M ( -- ) \ Define a method.
- :
- ;
-
-
- \ ====== Custom Abort routine =====================
- 80 USER (ABORT)
- VARIABLE ^ABORT
- : Ob.Abort ( n -- ) \ Use during class definition.
- #C.or.I? @ cr
- IF ." Class part" ;Class
- ELSE ." Instance part" ;Instance
- THEN
- ^ABORT @ (ABORT) ! ABORT
- ;
-
- \ ====== Message support ===========================
- : link>name 4 + ;
-
- : Compile.Meth ( meth.CFA ob.DFA -- )
- \
- \ the following line was edited out -- JL
- \ [compile] literal \ make a literal of ob.DFA
- \
- \ and replaced by the following four lines
- MOVE.L_#,D0 W,
- here - ,
- LEA_$-6(PC,D0.L),A0 ,
- MOVE.L_A0,-(A6) W,
-
- compile Opush \ compile a call to opush
- JSR_d(PC) W, here - W,
- compile Opop
- ;
-
- : Do.Meth ( meth.CFA ob.DFA -- )
- Opush execute Opop
- ;
-
- : Do.OR.Compile ( ob.DFA meth.CFA f<>0 -- )
- 1 =
- IF swap Do.Meth
- ELSE
- swap state @
- IF Compile.Meth
- ELSE Do.Meth THEN
- THEN
- ;
-
- GLOBAL
- : Find.Meth?
- { lfa strng.adr | f -- strng.adr CFA f<>0 }
- \ f = as with FIND
- 0 -> f
- BEGIN
- lfa link>name C@ %11111 and
- strng.adr C@ =
- IF 1 -> f strng.adr C@ L_ext 1+ 1
- DO strng.adr I + C@ lfa 4 + I + C@ <>
- IF 0 -> f leave THEN
- LOOP
- THEN
- f 0= lfa @ 0 <> and
- WHILE \ continue if meth <> message & LFA<>0
- lfa @ negate +> lfa
- REPEAT
- strng.adr f
- IF lfa dup link>body swap link>name C@
- %10000000 and
- IF 1 ELSE -1 THEN
- ELSE f
- THEN
- ;
-
- GLOBAL
- : Get.Meth ( key strng.adr -- meth.CFA f<>0 )
- Find.Meth?
- ?dup IF
- rot drop
- ELSE
- cr ." Method --> " count %11111 and
- type 3 spaces ." Not Found" ABORT
- THEN
- ;
-
- GLOBAL
- : Get.Msg ( -- strng.adr )
- 32 word pad over C@ L_ext 1+ cmove pad
- ;
-
- GLOBAL
- : Selector ( ob.DFA key -- ) ( <msg> -IN- )
- Get.Msg
- Get.Meth
- Do.OR.Compile
- ;
-
-
- CREATE Ob.Words
-
- \ ==== Define OBJECT ============================
- : :Root
- Create \ stopper word
- NP @ DictBase@ - ,
- 0 NP @ ! \ put 0 for class.Key
- 4 NP +! \ increment NP by 4 bytes
- ;
-
- :Root <root>
-
- \ ---- Define class section of OBJECT -----------
- here #c.Pvt.Tail !
-
- 0 offset !
- GLOBAL I.Var class.Key
- I.Var class.Tail
- I.Var c.Tail.link
- GLOBAL I.Var class.Size
- GLOBAL I.Var ins.Key
- I.Var ins.Tail
- I.Var i.Tail.link
- GLOBAL I.Var ins.Size
- I.Var parent
- I.Var Ob.name.link
- I.Var Class.RLA
- offset @ #class.Size !
-
- : cr5sp cr 5 spaces ;
-
- : <Pr.Meth> ( adr cnt -- )
- cr5sp %11111 and swap over type
- 25 swap - spaces ." Link adr = "
- dup . space ." Offset = " dup @ .
- ;
-
- : Pr.meths ( key -- )
- BEGIN
- dup @
- WHILE
- dup link>name count
- <Pr.Meth> dup @ -
- REPEAT drop
- ;
- CODE ClassStrucAllot ( n -- addr )
- MOVE.L $-1FC(A5),D0
- MOVE.L D0,D1
- ASR.L #$1,D1
- BCC.S @1
- ADDQ.L #$1,D0
- @1 MOVE.L D0,A0
- ADD.L (A6)+,D0
- MOVE.L D0,$-1FC(A5)
- MOVE.L A0,-(A6)
- MOVE.L #0,-(A6)
- RTS
- END-CODE
-
-
- : SetClassStruc ( -- )
- #class.Size @ ClassStrucAllot
- IF ." Memory error" . ." Handle" . abort
- ELSE
- dup DictBase@ - ,
- Opush
- #c.Head @ DictBase@ -
- class.Key !
- #c.Pub.Tail @ dup IF DictBase@ - THEN
- class.Tail !
- #c.Pub.Tail @ dup
- IF dup #c.Pvt.Tail @ =
- IF #Forth.Head @ -
- ELSE @ THEN
- THEN c.Tail.link !
- #class.Size @ class.Size !
- #i.Head @ DictBase@ -
- ins.Key !
- #i.Pub.Tail @ dup IF DictBase@ - THEN
- ins.Tail !
- #i.Pub.Tail @ dup
- IF dup #i.Pvt.Tail @ =
- IF #Forth.Head @ -
- ELSE @ THEN
- THEN i.Tail.link !
- #ins.Size @ ins.Size !
- #parent @ Parent !
- last DictBase@ - Class.RLA !
- last @ ob.name.link !
- Opop
- THEN
- ;
-
- here #c.Pub.Tail !
-
- :M pr.ob.ivar ( -- )
- cr cr ." Class instance variables are :"
- cr5sp ." class.Key = "
- class.Key @ DictBase@ + .
- cr5sp ." class.Tail = "
- class.Tail @ DictBase@ + .
- cr5sp ." c.Tail.link = "
- c.Tail.link @ .
- cr5sp ." class.Size = "
- class.Size @ .
- cr5sp ." ins.Key = "
- ins.Key @ DictBase@ + .
- cr5sp ." ins.Tail = "
- ins.Tail @ DictBase@ + .
- cr5sp ." i.Tail.link = "
- i.Tail.link @ .
- cr5sp ." ins.Size = "
- ins.Size @ .
- cr5sp ." Parent = "
- Parent @ DictBase@ + .
- cr5sp ." ob.name.link = "
- ob.name.link @ .
- cr5sp ." Class.RLA = "
- Class.RLA @ DictBase@ + .
- ;
- GLOBAL
- :M Pr.class.meths ( -- )
- cr cr ." Class methods are :"
- class.Key @ DictBase@ +
- Pr.meths
- ;
- GLOBAL
- :M Pr.ins.meths ( -- )
- cr cr ." Instance methods are :"
- ins.Key @ DictBase@ +
- Pr.meths
- ;
-
- GLOBAL
- :M Describe ( -- )
- cr ." ---- Class Information ---------------------------------------"
- cr ." NAME : " Class.RLA @ DictBase@ + dup .
- link>name count %11111 and type
- 5 spaces ." pointer to class data = " Ocop .
- Pr.ob.ivar
- Pr.class.meths
- Pr.ins.meths cr
- ;
-
- GLOBAL
- :M Define.Child.Class ( -- )
- last #Forth.Head !
- class.Size @ #class.Size !
- ins.Size @ #ins.Size !
- class.Key @ DictBase@ + #c.Head !
- 0 #c.Pvt.Tail !
- 0 #c.Pub.Tail !
- ins.Key @ DictBase@ + #i.Head !
- 0 #i.Pvt.Tail !
- 0 #i.Pub.Tail !
- Ocop DictBase@ - #parent !
- Relink.DefWords
- [ ' Ob.Abort body>link DictBase@ - ] literal
- DictBase@ + link>body (ABORT) dup @ ^ABORT ! !
-
- ;
-
- GLOBAL
- :M Name.Child.Class ( -- ) ( <name> -IN- )
- Delink.DefWords
- ^ABORT @ (ABORT) ! \ restore old abort routine
- CREATE immediate
- SetCLassStruc
-
- \ -- seal class and link to parent ------------
- last dup #Forth.Head @ - swap !
- #c.Pub.Tail @ ?dup \ false => no class section
- IF #c.Pvt.Tail @ dup #Forth.Head @ - swap !
- dup class.Key @ DictBase@ + - swap !
- THEN
- #i.Pub.Tail @ ?dup \ false => no class section
- IF #i.Pvt.Tail @ dup #Forth.Head @ - swap !
- dup ins.Key @ DictBase@ + - swap !
- THEN
-
- DOES> @ DictBase@ + dup @ DictBase@ + Selector
- ;
- GLOBAL
- :M Make.Instance ( -- ) ( <name> -IN- )
- CREATE immediate
- ins.Key @ ,
- ins.Size @ allot
- DOES> dup @ DictBase@ + Selector
- ;
-
- last #c.Head !
-
-
- \ -----Define instance section of root object ---------
-
- here #i.Pvt.Tail !
-
- 0 Offset !
-
- GLOBAL I.Var I.Key
-
- Offset @ #ins.Size !
- here #i.Pub.Tail !
-
- GLOBAL
- :M Pr.Imeths ( -- )
- I.Key @ DictBase@ +
- cr cr ." Instance methods are :"
- Pr.meths
- ;
- GLOBAL
- :M Name ( -- )
- cr ." NAME : " Ocop 4 - body>link link>name count
- %11111 and type 5 spaces ." instance.DFA = " I.Key .
- ;
- GLOBAL
- :M Describe ( -- )
- cr ." ---- Instance information ------------------------------------"
- Name
- Pr.Imeths
- ;
-
- last #i.Head !
-
-
- \ ---- Child Class defining words ------------------
- : Relink { t o k | -- } ( dfa -OS- dfa' )
- Class.RLA @ dup DictBase@ +
- dup @ Ob.name.link !
- swap k @ - swap !
- o @ t @ DictBase@ + dup @ o ! !
- ;
-
- : Relink.Parents ( -- )
- #parent @ DictBase@ + Opush
- #C.or.I? @
- IF
- Begin
- class.Key @
- While
- class.Tail dup @
- IF c.Tail.link class.Key
- Relink
- ELSE drop
- THEN Parent @ DictBase@ +
- Opop Opush
- Repeat
- ELSE
- Begin
- class.Key @
- While
- ins.Tail dup @
- IF i.Tail.link ins.Key
- Relink
- ELSE drop
- THEN Parent @ DictBase@ +
- Opop Opush
- Repeat
- THEN
- Opop
- ;
-
- : Delink { o t | -- } ( dfa -OS- dfa' )
- t @
- IF
- Ob.name.link @ Class.RLA @ DictBase@ + !
- o @ t @ DictBase@ + dup @ o ! !
- THEN
- Parent @ DictBase@ +
- Opop Opush
- ;
-
- : Delink.Parents ( -- )
- #parent @ DictBase@ + Opush
- #C.or.I? @
- IF
- Begin
- class.Key @ \ class.Key is zero for <root>
- While
- c.Tail.link class.Tail
- Delink
- Repeat
- ELSE
- Begin
- class.Key @ \ class.Key is zero for <root>
- While
- i.Tail.link ins.Tail
- Delink
- Repeat
- THEN
- Opop
- ;
-
- : <:Class> ( -- )
- #class.Size @ Offset !
- here #c.Pvt.Tail !
- here #c.Pub.Tail !
- -1 #C.or.I? !
- Relink.Parents
- ;
- Let: :Class Do: <:Class>
-
- : <;Class> ( -- )
- last #c.Head !
- Offset @ #class.Size !
- #c.Pvt.Tail @ body>link #c.Pvt.Tail !
- #c.Pub.Tail @ body>link #c.Pub.Tail !
- Delink.Parents
- ;
- Let: ;Class Do: <;Class>
-
- : <:Instance> ( -- )
- #ins.Size @ Offset !
- here #i.Pvt.Tail !
- here #i.Pub.Tail !
- 0 #C.or.I? !
- Relink.Parents
- ;
- Let: :Instance Do: <:Instance>
-
- : <;Instance> ( -- )
- last #i.Head !
- Offset @ #ins.Size !
- #i.Pvt.Tail @ body>link #i.Pvt.Tail !
- #i.Pub.Tail @ body>link #i.Pub.Tail !
- Delink.Parents
- ;
- Let: ;Instance Do: <;Instance>
-
- : <Hide>
- here #C.or.I? @
- IF #c.Pub.Tail ! ELSE #i.Pub.Tail ! THEN
- ;
-
- Let: Hide Do: <Hide>
-
- \ ------ Complete and Seal root object -----------
-
- : :OBJECT
- CREATE immediate \ make header for "OBJECT"
- DOES> @ DictBase@ + dup @ DictBase@ + Selector
- ;
-
- :OBJECT OBJECT
-
- \ -- Initialize temporary variables used by Set.Struc --
- ' <root> 4 + @ #parent !
- ' Ob.Words body>link #Forth.Head !
- #c.Pub.Tail @ body>link #c.Pub.Tail !
- #i.Pub.Tail @ body>link #i.Pub.Tail !
- #c.Pvt.Tail @ body>link #c.Pvt.Tail !
- #i.Pvt.Tail @ body>link #i.Pvt.Tail !
-
- SetClassStruc \ init class data structure
-
- \ -- seal class and link to <root> -----------------
- Delink.DefWords
- ' <root> body>link #parent !
- #i.Pub.Tail @ dup #parent @ - swap !
- #c.Pub.Tail @ dup #parent @ - swap !
- #i.Pvt.Tail @ dup #Forth.Head @ - swap !
- #c.Pvt.Tail @ dup #Forth.Head @ - swap !
- 0 ' <root> body>link
- last dup ' Ob.DefWords body>link - swap
- ! !
-
- \ ====== EXAMPLES ==================
- \ ====== Integer Class =============
- OBJECT Define.Child.Class
- :Instance
- I.Var Int
- Hide
- :M Fetch ( -- n )
- Int @
- ;
- :M Save ( n -- )
- Int !
- ;
- ;Instance
-
- OBJECT Name.Child.Class Integer
-
-
- \ ====== 10 cell Array Class ==============
- OBJECT Define.Child.Class
- :Instance
- 10 Constant Max.Size
- 10 4 * Ins.Array Head
- Hide
- :M Describe
- cr ." ---- Instance Information ---------------------------------"
- Name
- cr ." Max.Size (in cells) = " Max.Size .
- Pr.Imeths
- ;
- :M Store ( x i -- )
- \ Store value x in array for index = i
- Max.Size over 1 + < if ." index out of bounds" abort then
- 4 * Head + !
- ;
- :M Retrieve ( i -- )
- \ Retrieve value of array for index = i.
- Max.Size over 1 + < if ." index out of bounds" abort then
- 4 * Head + @
- ;
- ;Instance
- OBJECT Name.Child.Class Array10 ( -- )
-
-
- \ ====== Variable size Array Class ===============
- Integer Define.Child.Class
- :Instance
- I.Var Max.Index \ max size of array
- I.Var Length \ number of elements in array
- I.Pntr Start \ points to the start of array memory
- Hide
- :M Describe
- cr ." ---- Instance Information ---------------------------------"
- Name
- cr ." Max Length in cells = " Max.Index @ 1+ .
- cr ." Cell size in bytes = " Int @ .
- Pr.Imeths
- ;
- :M Store ( x i -- ) \ Store value x in array for index = i, first cell has index of zero
- Max.Index @ over < over 0 < or IF ." index out of bounds" abort THEN \ <-- error checking
- Int @ * Start + !
- ;
- :M Retrieve ( i -- ) \ Retrieve value of array for index = i.
- Max.Index @ over < over 0 < or IF ." index out of bounds" abort THEN \ <-- error checking
- Int @ * Start + @
- ;
- ;Instance
- :Class
- :M Make.Instance ( n c -- ) ( <name> -IN- )
- \ Array instance of size n cells, cell size of c
- CREATE immediate
- ins.Key @
- , \ store key to methods of parent class
- dup , \ save cell size in 'Int' variable
- over 1- , \ make and save Max.Index
- 0 , \ init current Length to zero
- * ins.Size @ + allot
- DOES> dup @ DictBase@ + Selector
- ;
- ;Class
- Integer Name.Child.Class Array ( n c -- )
-
-
- \ ====== Vector Class ================================
- Array Define.Child.Class
- :Class
- :M Make.Instance ( n -- )
- 4 Make.Instance
- ;
- ;Class
- Array Name.Child.Class Vector ( n -- )
-
-
- \ ====== String Class =================================
- Array Define.Child.Class
- :Class
- :M Make.Instance ( n -- )
- 1 Make.Instance
- ;
- ;Class
- :Instance
- :M Describe
- cr ." ---- Instance Information ---------------------------------"
- Name
- cr 5 spaces ." Max String length = " Max.Index @ 1+ .
- cr 5 spaces ." Current String length = " Length @ .
- Pr.Imeths
- ;
- :M Print ( -- ) \ Prints string for this instance.
- Start Length @ dup IF type ELSE ." string empty" drop drop THEN
- ;
- :M Store ( a -- ) \ Store a string with count byte at address.
- count dup Max.Index @ 2 + <
- IF dup Length ! Start swap cmove
- ELSE cr ." String too large for 'Store' " drop drop
- THEN
- ;
- ;Instance
- Array Name.Child.Class String ( n -- )
-
-
- \ ==== Struc Class =================================
- OBJECT Define.Child.Class
- :Class
- : Make.Instance ( -- ) ( name -IN- )
- CREATE immediate
- Ins.Key @ ,
- ins.Size @ allot
- DOES> dup @ DictBase@ + Get.Msg Get.Meth
- drop execute state @
- IF [compile] literal THEN
- ;
- ;Class
- :Instance
- : S.Array ( size -- ) ( name -IN- )
- CREATE
- offset @ ,
- dup 2 mod +
- offset +!
- DOES> @ +
- ;
- : LongInt ( -- ) ( name -IN- )
- 4 S.Array
- ;
- ;Instance
- OBJECT Name.Child.Class Struct
-
- \ ==== Point Class ========================
- Struct Define.Child.Class
- :Instance
- LongInt Xdim
- LongInt Ydim
- ;Instance
- Struct Name.Child.Class Point
-
-